package com.leha.mp.core.services.imp;

import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.leha.mp.core.config.WxPayConfig;
import com.leha.mp.core.constants.BizConstants;
import com.leha.mp.core.constants.CoreErrorDict;
import com.leha.mp.core.dao.*;
import com.leha.mp.core.entity.mybatis.*;
import com.leha.mp.core.entity.vo.OrderDetailVo;
import com.leha.mp.core.services.*;
import lombok.extern.log4j.Log4j2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
@Log4j2
public class OrderServicesImpl implements OrderServices {
    @Autowired
    PlDoctorPriceMapper priceMapper;
    @Autowired
    QaDoctorMapper doctorMapper;
    @Autowired
    PlOrderMapper orderMapper;
    @Autowired
    PlProductMapper productMapper;
    @Autowired
    PlConsultingMapper consultingMapper;
    @Autowired
    ConfluenceServices bizServices;
    @Autowired
    WAppServices appService;
    @Autowired
    AppDoctorServices doctorServices;
    @Autowired
    PlUserMapper userMapper;
    @Autowired
    PushServices pushServices;
    @Autowired
    BedgeServices bedgeServices;
    @Autowired
    CommonServicesImpl commonServices;
    @Autowired
    ErrorMessageServices errorMessageServices;

    @Autowired
    ValidateService validateService;


    @Override
    public PlOrder GenOrder(Integer uid, Integer did, Integer pid, String cip, String extraData) {

        PlOrder order = new PlOrder();
        QaDoctor doctor = doctorMapper.selectByPrimaryKey(did);
        PlProduct product = productMapper.selectByPrimaryKey(pid);


        // 判断咨询时间是否合法
        if (this.isConsultingTypeNeedCheck(product.getType().byteValue())
                && ! validateService.isConsultingTimeValidate(extraData, did, uid)) {
            return null;
        }

        Double price = product.getPrice();
        String body = product.getDes();
        order.setOrderFee((int)(price*100));
        order.setOrderBody(body);
        order.setOrderDetail(product.getPrice().toString()+"元/"+product.getUnitType());
        order.setProductId(pid);
        order.setUid(uid);
        order.setPayType("JSAPI");
        order.setUserIp(cip);
        order.setOrderNo(String.format("PLYK%05d%d%d", uid, pid, System.currentTimeMillis()));
        orderMapper.insertSelective(order);

        if(bizServices.isConsulting(product.getType())) {
            log.info("咨询类订单，生成对应咨询信息");
            if(bizServices.genConsulting(uid, order.getOrderId(), product, extraData, false) == null) {
                errorMessageServices.setError(CoreErrorDict.ArrangeTimeInvalide);
                return null;
            }
        }

        return order;
    }

    @Override
    public void OrderPaySuccess(String orderNo, Date payTime, String transactionId, String result, String msg) {
        PlOrderExample ex = new PlOrderExample();
        ex.createCriteria().andOrderNoEqualTo(orderNo);
        List<PlOrder> orders = orderMapper.selectByExample(ex);
        if(orders.size()!=1) {
            log.error("无效的订单编号："+orderNo);
            return;
        }
        PlOrder or = orders.get(0);
        if(or.getOrderStatus()!=BizConstants.Order_Status_Inited) {
            log.info("重复回调，直接退出");
            return;
        }
        or.setTransactionid(transactionId);
        or.setPayTime(payTime);

        if(result.equals("SUCCESS")) {
            or.setOrderStatus((byte) 1);
            orderMapper.updateByPrimaryKeySelective(or);
            bizServices.userPaySuccess(or);
            log.info("用户支付成功");
        } else {
            or.setOrderStatus((byte) 2);
            orderMapper.updateByPrimaryKeySelective(or);
            log.info("用户支付失败");
        }

    }

    @Override
    public boolean cancelOrder(Integer userId, Integer orderId) {
        PlOrder order = orderMapper.selectByPrimaryKey(orderId);
        if(order==null) {
            log.info("订单不存在");
            return false;
        }
        if(!order.getOrderStatus().equals(BizConstants.Order_Status_Payed)) {
            log.info("订单不是已支付状态"+order.getOrderStatus());
            return false;
        }
        PlConsultingExample ex = new PlConsultingExample();
        ex.createCriteria().andOrderIdEqualTo(orderId);
        List<PlConsulting> consultingList = consultingMapper.selectByExample(ex);
        if(consultingList.size()<=0) {
            log.info("咨询单不存在");
            return false;
        }

        PlConsulting consulting = consultingList.get(0);
        if(consulting.getStatus().equals(BizConstants.Consulting_Status_Payed)) {
            wxPayRefund(order);
        } else if (consulting.getStatus().equals(BizConstants.Consulting_Status_Accepted)) {
            consulting.setStatus(BizConstants.Consulting_Status_RefundDoubleCheck);
            consultingMapper.updateByPrimaryKeySelective(consulting);
        }
        return true;
    }

    @Override
    public boolean cancelConsulting(Integer consultingId) {
        PlConsulting consulting = consultingMapper.selectByPrimaryKey(consultingId);
        if(consulting == null) {
            return false;
        }
        if(!bizServices.canCancel(consulting.getStatus())) {
            return false;
        }
        consulting.setStatus(BizConstants.Consulting_Status_Refunded);
        PlOrder order = orderMapper.selectByPrimaryKey(consulting.getOrderId());
        consultingMapper.updateByPrimaryKeySelective(consulting);
        wxPayRefund(order);
        return true;
    }

    @Override
    public boolean cancelOrder(Integer orderId) {
        PlOrder or = orderMapper.selectByPrimaryKey(orderId);
        wxPayRefund(or);
        return true;
    }

    private void wxPayRefund(PlOrder order) {
        WxPayRefundRequest request = new WxPayRefundRequest();
        request.setTransactionId(order.getTransactionid());
        request.setOutRefundNo(order.getOrderNo());
        request.setTotalFee(order.getOrderFee());
        request.setRefundFee(order.getOrderFee());
        request.setNotifyUrl(WxPayConfig.getRefundNotifyUrl());
        try {
            appService.getPayServices().refund(request);
            //pushServices.SendMessageToUserWithMp(order.getUid(), "已为您进行退款处理。");
        } catch (WxPayException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void OrderRefundSuccess(String refundNo, String result, String msg) {
        log.info("用户退款回调");
        if(result.equals("SUCCESS")) {
            PlOrderExample ex = new PlOrderExample();
            ex.createCriteria().andOrderNoEqualTo(refundNo);
            List<PlOrder> orders = orderMapper.selectByExample(ex);
            if(orders.size()!=1) {
                log.error("退款无效的订单编号："+refundNo);
                return;
            }
            PlOrder or = orders.get(0);
            or.setOrderStatus(BizConstants.Order_Status_Refund);
            orderMapper.updateByPrimaryKeySelective(or);
            bedgeServices.UpdateUserBedge(or.getUid(), BedgeServices.Type_User_My_Order, or.getOrderId(), 1);
            log.info("用户退款成功");
        } else{
            log.info("用户退款失败，不做处理");
        }
    }

    @Override
    public Integer getOrderConsulting(Integer orderId) {
        PlConsultingExample ex = new PlConsultingExample();
        ex.createCriteria().andOrderIdEqualTo(orderId);
        List<PlConsulting> res = consultingMapper.selectByExample(ex);
        if(res.size()==0) {
            return 0;
        }
        return res.get(0).getConsultingId();
    }

    @Override
    public OrderDetailVo getOrderDetail(Integer orderId) {
        OrderDetailVo v = new OrderDetailVo();
        v.setOrderInfo(orderMapper.selectByPrimaryKey(orderId));
        v.setProductInfo(productMapper.selectByPrimaryKey(v.getOrderInfo().getProductId()));
        v.setDoctorInfo(doctorServices.getDoctorBaseInfo(v.getProductInfo().getDoctorId()));
        v.setUserInfo(userMapper.selectByPrimaryKey(v.getOrderInfo().getUid()));
        PlConsultingExample ex = new PlConsultingExample();
        ex.createCriteria().andOrderIdEqualTo(orderId);
        List<PlConsulting> res = consultingMapper.selectByExample(ex);
        v.setConsultingInfo(res.get(0));
        return v;
    }

    @Override
    public Boolean cancelConsultingByUser(Integer consultingId) {
        PlConsulting consulting = consultingMapper.selectByPrimaryKey(consultingId);
        if(consulting==null) {
            log.info("咨询单不存在");
            return false;
        }
        if(consulting.getStatus()==BizConstants.Consulting_Status_Payed) {
            if(consulting.getOrderId()!=0) {
                wxPayRefund(orderMapper.selectByPrimaryKey(consulting.getOrderId()));
            } else {
                commonServices.refundConsultForVips(consulting.getUserId(), consulting.getDoctorId(), consulting.getConsultingType());
            }
            consulting.setStatus(BizConstants.Consulting_Status_Refunded);
            consultingMapper.updateByPrimaryKeySelective(consulting);
        } else if (consulting.getStatus()==BizConstants.Consulting_Status_Accepted) {
            consulting.setStatus(BizConstants.Consulting_Status_RefundDoubleCheck);
            consultingMapper.updateByPrimaryKeySelective(consulting);
        } else {
            log.info("不是已支付或者确认中的订单");
            return false;
        }
        return true;
    }

    private boolean isConsultingTypeNeedCheck(byte consultingType) {
        return (consultingType == BizConstants.Consulting_Type_Phone || consultingType == BizConstants.Consulting_Type_Video);
    }
}
